/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tom.social.analyzer.graph;

import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.DirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.DirectedSparseVertex;
import edu.uci.ics.jung.utils.UserDataContainer.CopyAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import pl.tom.social.dal.SocialDatabaseFacade;
import pl.tom.social.dal.entity.Site;

/**
 *
 * @author Tom
 */
public class GraphBuilder {

	private static final Logger logger = Logger.getLogger(GraphBuilder.class);
	private Map<String, Vertex> vertexNames = null;
	private List<Site> sites = null;
	private Graph graph = null;
	private Date start = null;
	private Date end = null;
	private boolean links = false;

	public GraphBuilder(List<Site> sites) {
		this.sites = sites;
		vertexNames = new HashMap<String, Vertex>();
	}

	/**
	 * @param start the start to set
	 */
	public void setStart(Date start) {
		this.start = start;
	}

	/**
	 * @param end the end to set
	 */
	public void setEnd(Date end) {
		this.end = end;
	}

	/**
	 * @param links the links to set
	 */
	public void setLinks(boolean links) {
		this.links = links;
	}

	/**
	 * @return the graph
	 */
	public Graph getGraph() {
		if(graph == null) {
			build();
		}
		return graph;
	}

	public Graph build() {
		graph = new DirectedSparseGraph();
		SocialDatabaseFacade db = new SocialDatabaseFacade();
		List<String> sitesUrl = new ArrayList<String>();

		filterByDate();

		if(!links) {
			for(Site site : sites) {
				sitesUrl.add(site.getUrl());
			}
		}

		for(Site site : sites) {
			List<String> conns = db.getSiteLinksUrls(site);
			if(!links) {
				for(Iterator<String> iter = conns.iterator(); iter.hasNext();) {
					String conn = iter.next();
					if(!sitesUrl.contains(conn)) {
						iter.remove();
					}
				}
			}
			addVertex(site.getUrl(), conns);
		}

		return getGraph();
	}

	private void addVertex(String node, Collection<String> conns) {
		Vertex v;
		if(vertexNames.containsKey(node)) {
			v = vertexNames.get(node);
		} else {
			v = new DirectedSparseVertex();
			vertexNames.put(node, v);
			getGraph().addVertex(v);
		}
		v.setUserDatum("url", node, new CopyAction.Clone());

		for(String conn : conns) {
			if(SocialNetworkManager.getInstance().isServerAllowed(conn)) {
				Vertex c;
				if(vertexNames.containsKey(conn)) {
					c = vertexNames.get(conn);
				} else {
					c = new DirectedSparseVertex();
					vertexNames.put(conn, c);
					getGraph().addVertex(c);
				}
				c.setUserDatum("url", conn, new CopyAction.Clone());

				Edge e = new DirectedSparseEdge(v, c);
				getGraph().addEdge(e);
			}
		}
	}

	private void filterByDate() {
		for(Iterator<Site> iter = sites.iterator(); iter.hasNext();) {
			Site site = iter.next();
			if(site.getAdded().after(end) || site.getAdded().before(start)) {
				iter.remove();
			}
		}
	}
}
